/*************************************************************************
    > File Name: SHA256.h
    > Author: ZhaoLulu@BJTU
    > E-mail: 19281121@bjtu.edu.cn
    > Created Time: 2021年12月14日 星期二
 ************************************************************************/
#ifndef INC_19281121_6_HASH_SHA256_H
#define INC_19281121_6_HASH_SHA256_H
#define Conditional(x, y, z) ((x & y) ^ ((~x) & z))
#define Majority(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
#define LSigma_0(x) (ROT_L(x,30) ^ ROT_L(x,19) ^ ROT_L(x,10))
#define LSigma_1(x) (ROT_L(x,26) ^ ROT_L(x,21) ^ ROT_L(x,7))
#define SSigma_0(x) (ROT_L(x,25) ^ ROT_L(x,14) ^ SHR(x,3))
#define SSigma_1(x) (ROT_L(x,15) ^ ROT_L(x,13) ^ SHR(x,10))
#define MAX 1000

#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>

using namespace std;

typedef unsigned int UInt32;
typedef unsigned char UChar;

struct Message_Digest {
    UInt32 H[8];
};

class SHA256 {
public:
    string DO(UChar Y[]) {
        INIT();
        PAD(Y);
        MD = DEAL(M);
        return PRINT(MD);
    }

    string PRINT(Message_Digest md);

    Message_Digest DEAL(UInt32 m[16]);

    void INIT();

    void PAD(UChar Y[MAX]);

    UInt32 ROT_L(UInt32 W, int n);

    UInt32 SHR(UInt32 W, int n);

    Message_Digest MD;

    UInt32 W[MAX / 4];

    UInt32 M[16];
};

#endif //INC_19281121_6_HASH_SHA256_H
